use std::error::Error;
use serde::{Deserialize, Serialize};
use crate::g_rt;
use crate::KV_EVENT_SUBJECT;
use crate::NATS_CLIENT;


pub type WorkerId = i64;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct LocalBlockHash(pub u64);

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ExternalSequenceBlockHash(pub u64);

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct KvCacheStoredBlockData {
    pub block_hash: ExternalSequenceBlockHash,
    pub tokens_hash: LocalBlockHash,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct KvCacheStoreData {
    pub parent_hash: Option<ExternalSequenceBlockHash>,
    pub blocks: Vec<KvCacheStoredBlockData>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct KvCacheRemoveData {
    pub block_hashes: Vec<ExternalSequenceBlockHash>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum KvCacheEventData {
    Stored(KvCacheStoreData),
    Removed(KvCacheRemoveData),
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct KvCacheEvent {
    pub event_id: u64,
    pub data: KvCacheEventData,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouterEvent {
    pub worker_id: WorkerId,
    pub event: KvCacheEvent,
}

impl Serialize for LocalBlockHash {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_u64(self.0)
    }
}

impl<'de> Deserialize<'de> for LocalBlockHash {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = u64::deserialize(deserializer)?;
        Ok(LocalBlockHash(value))
    }
}

impl Serialize for ExternalSequenceBlockHash {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_u64(self.0)
    }
}

impl<'de> Deserialize<'de> for ExternalSequenceBlockHash {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = u64::deserialize(deserializer)?;
        Ok(ExternalSequenceBlockHash(value))
    }
}

pub fn publish_event(event: &(impl Serialize + Send + Sync + std::fmt::Debug)) -> Result<(), Box<dyn Error>> {
    let bytes: Vec<u8> = serde_json::to_vec(event)?;

    let client_guard = NATS_CLIENT.lock().unwrap();
    let client = client_guard.as_ref().ok_or("NATS client not initialized")?;

    g_rt.block_on(async{
        client.publish(KV_EVENT_SUBJECT.clone(), bytes.into()).await?;
        Ok(())
    })
}
